package com.crashcollection.util.http;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Proxy;
import android.util.Log;

/**
 * @ClassName: HttpRequest
 * @Description: HTTP通讯基类
 * @author Administrator
 * @date 2012-2-1 上午09:50:25
 */
public class HttpRequest implements IHttpRequest {
                                                                  
	private final static int ND_HTTP_ERROR = -1;                  
	private final static int ND_SOCKET_TIMEOUT_ERROR = -2;        
	private final static int ND_SOCKET_ERROR = -3;                
	private final static int ND_CONNECT_TIMEOUT_ERROR = -4;       
	private final static int ND_UNKNOWN_HOST_ERROR = -5;          
                                                                  
	protected String TAG = "HttpRequest";

	private final String GZIP = "gzip";

	private final String ACCEPT_ENCODEING = "Accept-Encoding";

	private final int mConnectTimeOut = 20000; // 20秒

	private final int mReadTimeOut = 60000;// 60秒

	private static IHttpRequest mHttp;

	protected Context mContext;

	public static IHttpRequest getInstance(Context ctx) {
		if (mHttp == null) {
			mHttp = new HttpRequest(ctx);
		}
		return mHttp;
	}

	public HttpRequest(Context ctx) {
		mContext = ctx.getApplicationContext();
	}

	/**
	 * @n<b>添加自定义头</b> :setHttpHeader
	 * @brief
	 * @see
	 * @param @param request
	 * @return void
	 * @<b>作者</b> : yanyy
	 * @<b>创建时间</b> : 2011-10-14下午04:04:09
	 */
	protected void setHttpHeader(HttpRequestBase request) {
		request.addHeader(ACCEPT_ENCODEING, GZIP);
	}

	@Override
	public int doDelete(String mStrURL, StringBuilder receive) {
		// int nRet = R.string.nd_http_error;
		int nRet = ND_HTTP_ERROR;
		InputStream inputStream = null;
		receive.delete(0, receive.length());
		try {
			// make a DELETE client
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams,
					mConnectTimeOut);
			HttpConnectionParams.setSoTimeout(httpParams, mReadTimeOut);
			HttpClientParams.setRedirecting(httpParams, true);
			HttpClient client = new DefaultHttpClient(httpParams);

			// 检查代理设置
			checkProxy(client);

			HttpDelete request = new HttpDelete(mStrURL);

			setHttpHeader(request);

			// POST and get response code
			HttpResponse response = client.execute(request);
			nRet = response.getStatusLine().getStatusCode();
			// get response string
			inputStream = response.getEntity().getContent();

			Header contentEncoding = response
					.getFirstHeader(HTTP.CONTENT_ENCODING);
			// 判断是否有压缩
			if (contentEncoding != null
					&& contentEncoding.getValue().equalsIgnoreCase(GZIP)) {
				inputStream = new GZIPInputStream(inputStream);
			}
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream));

			String line = "";
			String NL = System.getProperty("line.separator");
			while ((line = in.readLine()) != null) {
				receive.append(line + NL);
			}

			if (nRet == HttpStatus.SC_OK || nRet == HttpStatus.SC_CREATED) {

			} else {
				if (receive.length() <= 0)
					receive.append(response.getStatusLine().getReasonPhrase());
				if (receive.length() > 0)
					Log.v(TAG, receive.toString());
				Log.v(TAG, "nRet=" + nRet + ", url = " + mStrURL);
			}
		} catch (SocketTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_timeout_error;
			nRet = ND_SOCKET_TIMEOUT_ERROR;
		} catch (SocketException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_error;
			nRet = ND_SOCKET_ERROR;
		} catch (ConnectTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_connect_timeout_error;
			nRet = ND_CONNECT_TIMEOUT_ERROR;
		} catch (UnknownHostException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_unknown_host_error;
			nRet = ND_UNKNOWN_HOST_ERROR;
		} catch (Exception e) {
			Log.e(TAG, getErrMsg(e));
			receive.append(getErrMsg(e));
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioe) {
					Log.e(TAG, ioe.toString());
				}
			}
		}

		return nRet;
	}

	@Override
	public int doGet(String mStrURL, StringBuilder receive) {
		// int nRet = R.string.nd_http_error;
		int nRet = ND_HTTP_ERROR;
		InputStream inputStream = null;
		receive.delete(0, receive.length());
		try {
			// make a GET client
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams,
					mConnectTimeOut);
			HttpConnectionParams.setSoTimeout(httpParams, mReadTimeOut);
			HttpClientParams.setRedirecting(httpParams, true);
			HttpClient client = new DefaultHttpClient(httpParams);

			// 检查代理设置
			checkProxy(client);

			HttpGet request = new HttpGet();
			request.setURI(new URI(mStrURL));

			setHttpHeader(request);

			// sending request
			HttpResponse response = client.execute(request);
			nRet = response.getStatusLine().getStatusCode();

			// get response code and string
			inputStream = response.getEntity().getContent();
			Header contentEncoding = response
					.getFirstHeader(HTTP.CONTENT_ENCODING);
			// 判断是否有压缩
			if (contentEncoding != null
					&& contentEncoding.getValue().equalsIgnoreCase(GZIP)) {
				inputStream = new GZIPInputStream(inputStream);
			}
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream));
			String line = "";
			String NL = System.getProperty("line.separator");
			while ((line = in.readLine()) != null) {
				receive.append(line + NL);
			}

			if (nRet == HttpStatus.SC_OK || nRet == HttpStatus.SC_CREATED) {

			} else {
				if (receive.length() <= 0)
					receive.append(response.getStatusLine().getReasonPhrase());
				if (receive.length() > 0)
					Log.v(TAG, receive.toString());
				Log.v(TAG, "nRet=" + nRet + ", url = " + mStrURL);
			}

		} catch (SocketTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_timeout_error;
			nRet = ND_SOCKET_TIMEOUT_ERROR;
		} catch (SocketException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_error;
			nRet = ND_SOCKET_ERROR;
		} catch (ConnectTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_connect_timeout_error;
			nRet = ND_CONNECT_TIMEOUT_ERROR;
		} catch (UnknownHostException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_unknown_host_error;
			nRet = ND_UNKNOWN_HOST_ERROR;
		} catch (Exception e) {
			Log.e(TAG, getErrMsg(e));
			receive.append(getErrMsg(e));
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioe) {
					Log.e(TAG, ioe.toString());
				}
			}
		}

		return nRet;
	}

	@Override
	public int doPut(String mStrURL, JSONObject c, StringBuilder receive) {
		return doPut(mStrURL, c.toString(), receive);
	}

	@Override
	public int doPost(String mStrURL, JSONObject c, StringBuilder receive) {
		return doPost(mStrURL, c.toString(), receive);
	}

	// 检查代理设置
	private void checkProxy(HttpClient client) {
		HttpHost proxyHost = null;
		// 只有wap才需要设置代理
		if (needToProxy(mContext)) {
			if (Proxy.getDefaultHost() != null) {
				proxyHost = new HttpHost(Proxy.getDefaultHost(),Proxy.getDefaultPort());
				if (proxyHost != null) {
					client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxyHost);
				}
			}
		}
	}

	@Override
	public int doPut(String mStrURL, String content, StringBuilder receive) {
		// int nRet = R.string.nd_http_error;
		int nRet = ND_HTTP_ERROR;
		InputStream inputStream = null;
		receive.delete(0, receive.length());
		try {
			// make a PUT client
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams,
					mConnectTimeOut);
			HttpConnectionParams.setSoTimeout(httpParams, mReadTimeOut);
			HttpClientParams.setRedirecting(httpParams, true);
			HttpClient client = new DefaultHttpClient(httpParams);

			// 检查代理设置
			checkProxy(client);

			HttpPut request = new HttpPut(mStrURL);

			setHttpHeader(request);

			// get json string and pass to entigy
			HttpEntity entity;
			// StringEntity s = new
			// StringEntity(StrFun.StringToUnicode(c.toString()), HTTP.UTF_8);
			StringEntity s = new StringEntity(content, HTTP.UTF_8);
			s.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
					"application/json"));
			s.setContentEncoding(new BasicHeader(HTTP.CONTENT_ENCODING,
					HTTP.UTF_8));

			entity = s;
			request.setEntity(entity);

			// POST and get response code
			HttpResponse response = client.execute(request);
			nRet = response.getStatusLine().getStatusCode();
			// get response string
			inputStream = response.getEntity().getContent();

			Header contentEncoding = response
					.getFirstHeader(HTTP.CONTENT_ENCODING);
			// 判断是否有压缩
			if (contentEncoding != null
					&& contentEncoding.getValue().equalsIgnoreCase(GZIP)) {
				inputStream = new GZIPInputStream(inputStream);
			}
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream));

			String line = "";
			String NL = System.getProperty("line.separator");
			while ((line = in.readLine()) != null) {
				receive.append(line + NL);
			}

			if (nRet == HttpStatus.SC_OK || nRet == HttpStatus.SC_CREATED) {

			} else {
				if (receive.length() <= 0)
					receive.append(response.getStatusLine().getReasonPhrase());
				if (receive.length() > 0)
					Log.v(TAG, receive.toString());
				Log.v(TAG, "nRet=" + nRet + ", url = " + mStrURL + ", send="
						+ content);
			}
		} catch (SocketTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_timeout_error;
			nRet = ND_SOCKET_TIMEOUT_ERROR;
		} catch (SocketException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_error;
			nRet = ND_SOCKET_ERROR;
		} catch (ConnectTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_connect_timeout_error;
			nRet = ND_CONNECT_TIMEOUT_ERROR;
		} catch (UnknownHostException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_unknown_host_error;
			nRet = ND_UNKNOWN_HOST_ERROR;
		} catch (Exception e) {
			Log.e(TAG, getErrMsg(e));
			receive.append(getErrMsg(e));
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioe) {
					Log.e(TAG, ioe.toString());
				}
			}
		}

		return nRet;
	}

	@Override
	public int doPost(String mStrURL, String content, StringBuilder receive) {
		// int nRet = R.string.nd_http_error;
		int nRet = ND_HTTP_ERROR;
		InputStream inputStream = null;
		receive.delete(0, receive.length());
		try {
			// make a POST client
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams,
					mConnectTimeOut);
			HttpConnectionParams.setSoTimeout(httpParams, mReadTimeOut);
			HttpClientParams.setRedirecting(httpParams, true);
			HttpClient client = new DefaultHttpClient(httpParams);

			// 检查代理设置
			checkProxy(client);

			HttpPost request = new HttpPost(mStrURL);

			setHttpHeader(request);

			// get json string and pass to entigy
			HttpEntity entity;
			// StringEntity s = new
			// StringEntity(StrFun.StringToUnicode(c.toString()),
			// HTTP.UTF_8);
			StringEntity s = new StringEntity(content, HTTP.UTF_8);
			s.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
					"application/json"));
			s.setContentEncoding(new BasicHeader(HTTP.CONTENT_ENCODING,
					HTTP.UTF_8));

			entity = s;
			request.setEntity(entity);

			// POST and get response code
			HttpResponse response = client.execute(request);
			nRet = response.getStatusLine().getStatusCode();
			// get response string
			inputStream = response.getEntity().getContent();

			Header contentEncoding = response
					.getFirstHeader(HTTP.CONTENT_ENCODING);
			// 判断是否有压缩
			if (contentEncoding != null
					&& contentEncoding.getValue().equalsIgnoreCase(GZIP)) {
				inputStream = new GZIPInputStream(inputStream);
			}
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream));

			String line = "";
			String NL = System.getProperty("line.separator");
			while ((line = in.readLine()) != null) {
				receive.append(line + NL);
			}

			if (nRet == HttpStatus.SC_OK || nRet == HttpStatus.SC_CREATED) {

			} else {
				if (receive.length() <= 0)
					receive.append(response.getStatusLine().getReasonPhrase());
				if (receive.length() > 0)
					Log.v(TAG, receive.toString());
				Log.v(TAG, "nRet=" + nRet + ", url = " + mStrURL + ", send="
						+ content);
			}
		} catch (SocketTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_timeout_error;
			nRet = ND_SOCKET_TIMEOUT_ERROR;
		} catch (SocketException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_error;
			nRet = ND_SOCKET_ERROR;
		} catch (ConnectTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_connect_timeout_error;
			nRet = ND_CONNECT_TIMEOUT_ERROR;
		} catch (UnknownHostException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_unknown_host_error;
			nRet = ND_UNKNOWN_HOST_ERROR;
		} catch (Exception e) {
			Log.e(TAG, getErrMsg(e));
			receive.append(getErrMsg(e));
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioe) {
					Log.e(TAG, ioe.toString());
				}
			}
		}

		return nRet;
	}

	@Override
	public int doDownFile(String mStrURL, File saveFile) {
		// int nRet = R.string.nd_http_error;
		int nRet = ND_HTTP_ERROR;
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			// make a get client
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams,
					mConnectTimeOut);
			HttpConnectionParams.setSoTimeout(httpParams, mReadTimeOut);
			HttpClientParams.setRedirecting(httpParams, true);
			HttpClient client = new DefaultHttpClient(httpParams);

			// 检查代理设置
			checkProxy(client);

			HttpGet request = new HttpGet();
			request.setURI(new URI(mStrURL));

			setHttpHeader(request);

			// sending request
			HttpResponse response = client.execute(request);
			nRet = response.getStatusLine().getStatusCode();

			// get response code and string
			inputStream = response.getEntity().getContent();
			Header contentEncoding = response
					.getFirstHeader(HTTP.CONTENT_ENCODING);
			// 判断是否有压缩
			if (contentEncoding != null
					&& contentEncoding.getValue().equalsIgnoreCase(GZIP)) {
				inputStream = new GZIPInputStream(inputStream);
			}

			// 把文件存到path
			if (saveFile.exists()) {
				saveFile.delete();
			}
			outputStream = new FileOutputStream(saveFile);
			byte buf[] = new byte[1024];
			int byteread = 0;
			while ((byteread = inputStream.read(buf)) != -1) {
				outputStream.write(buf, 0, byteread);
			}

			if (nRet == HttpStatus.SC_OK || nRet == HttpStatus.SC_CREATED) {

			} else {
				Log.v(TAG, "nRet=" + nRet + ", url = " + mStrURL);
			}

		} catch (SocketTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_timeout_error;
			nRet = ND_SOCKET_TIMEOUT_ERROR;
		} catch (SocketException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_error;
			nRet = ND_SOCKET_ERROR;
		} catch (ConnectTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_connect_timeout_error;
			nRet = ND_CONNECT_TIMEOUT_ERROR;
		} catch (UnknownHostException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_unknown_host_error;
			nRet = ND_UNKNOWN_HOST_ERROR;
		} catch (Exception e) {
			if (saveFile.exists()) {
				saveFile.delete();
			}
			Log.e(TAG, getErrMsg(e));
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioe) {
					Log.e(TAG, ioe.toString());
				}
			}
			if (outputStream != null)
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

		return nRet;
	}

	@Override
	public int doPost(String mStrURL, byte[] b, StringBuilder receive) {
		// int nRet = R.string.nd_http_error;
		int nRet = ND_HTTP_ERROR;
		InputStream inputStream = null;
		receive.delete(0, receive.length());
		try {
			// make a POST client
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams,
					mConnectTimeOut);
			HttpConnectionParams.setSoTimeout(httpParams, mReadTimeOut);
			HttpClientParams.setRedirecting(httpParams, true);
			HttpClient client = new DefaultHttpClient(httpParams);

			checkProxy(client);

			HttpPost request = new HttpPost(mStrURL);

			setHttpHeader(request);

			ByteArrayEntity byteArray = new ByteArrayEntity(b);

			request.setEntity(byteArray);
			// POST and get response code
			HttpResponse response = client.execute(request);
			nRet = response.getStatusLine().getStatusCode();
			// get response string
			inputStream = response.getEntity().getContent();

			Header contentEncoding = response
					.getFirstHeader(HTTP.CONTENT_ENCODING);
			// 判断是否有压缩
			if (contentEncoding != null
					&& contentEncoding.getValue().equalsIgnoreCase(GZIP)) {
				inputStream = new GZIPInputStream(inputStream);
			}
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream));

			String line = "";
			String NL = System.getProperty("line.separator");
			while ((line = in.readLine()) != null) {
				receive.append(line + NL);
			}

			if (nRet == HttpStatus.SC_OK || nRet == HttpStatus.SC_CREATED) {

			} else {
				if (receive.length() <= 0)
					receive.append(response.getStatusLine().getReasonPhrase());
				if (receive.length() > 0)
					Log.v(TAG, receive.toString());
				Log.v(TAG, "nRet=" + nRet + ", url = " + mStrURL);
			}
		} catch (SocketTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_timeout_error;
			nRet = ND_SOCKET_TIMEOUT_ERROR;
		} catch (SocketException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_socket_error;
			nRet = ND_SOCKET_ERROR;
		} catch (ConnectTimeoutException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_connect_timeout_error;
			nRet = ND_CONNECT_TIMEOUT_ERROR;
		} catch (UnknownHostException e) {
			Log.e(TAG, getErrMsg(e));
			// nRet = R.string.nd_unknown_host_error;
			nRet = ND_UNKNOWN_HOST_ERROR;
		} catch (Exception e) {
			Log.e(TAG, getErrMsg(e));
			receive.append(getErrMsg(e));
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioe) {
					Log.e(TAG, ioe.toString());
				}
			}
		}

		return nRet;
	}

	private String getErrMsg(Exception e) {
		String msg = e.getMessage();
		if (msg == null) {
			msg = e.toString();
		}
		return msg;
	}

	// ////////////////////////////////////// 代理控制
	// ///////////////////////////////////////
	private boolean needToProxy(Context context) {
		ConnectivityManager connectivityManager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		if (connectivityManager == null) {
			return false;
		}

		NetworkInfo info = connectivityManager.getActiveNetworkInfo();
		if (info == null) {
			return false;
		}

		String type = info.getTypeName();

		if (type.equalsIgnoreCase("MOBILE")) { // GPRS方式

			String apnStr = info.getExtraInfo();
			if (apnStr != null) {
				apnStr = apnStr.toLowerCase();
				if (apnStr.contains("wap")) { // WAP方式
					String proxyHost = android.net.Proxy.getDefaultHost();
					if (proxyHost != null && !proxyHost.equals("")) {
						return true;
					}
				}
			}
		}
		return false;
	}

}
